<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body style="background-color: #1e293b;color: #c9d1d9;">
    <h1 id="app"></h1>
    <script> 
    
        //副作用函数栈，存放所有副作用函数
        //修改[data->Map[name:Set(fn1,fn2...)],data2->Map[name:Set(fn1,fn2...)]]
        const e_stack = new WeakMap();  
        //正在执行的副作用函数
        let activeEffect = null;
        //判断是否是对象
        function isObject(value){
            return typeof value === 'object' && value !== null
        }
         
      
        //收集依赖
        function track(target,key){
          if(!activeEffect) return
          let depMap = e_stack.get(target);
          if(!depMap){
              depMap = new Map();
              e_stack.set(target,depMap)
          }

          let depSet = depMap.get(key);
          if(!depSet){
              depSet = new Set();
              depMap.set(key,depSet)
          }
          
          depSet.add(activeEffect)
        }
        
         //触发依赖
         function trigger(target,key){
             let depMap = e_stack.get(target);
             if(!depMap) return;
             
             let depSet = depMap.get(key)
             if(depSet)  depSet.forEach( fn=> fn())
         }
       
        /**
         * 创建响应式数据
         * @param [object]: 普通对象
         * @return [Proxy]: 代理对象
         */
        function reactive(obj){
          if(!isObject(obj)) return;
          
          return new Proxy(obj,{
            get(target,key){
              track(target,key)    //收集
              return target[key]
            },
            set(target,key,value){
              target[key] = value;
              trigger(target,key)  //触发依赖中的副作用函数
              return true;
            }
          })
        }
       
       /**
        * 注册副作用函数
        * @param [function]: 需要注册的副作用函数
        */
       function effect(fn){
         if(typeof fn !== 'function') return
         activeEffect = fn    //记录正在执行的副作用函数
         fn()                 //调用副作用函数         
         activeEffect = null  //重置全局变量
       }
    
        //将对象设置为响应式数据
        const data = reactive( { name : 'xiaohong', age: 3} )
        const data2 = reactive( { name : 'xxh', age: 18} )

        //副作用函数
        function e1(){
          console.log('e1...',data.name);  //压入Map
        }
        effect(e1)
        
        function e2(){
          console.log('e2...',data2.name);  //压入Map
        }
        effect(e2)

    

        setTimeout(()=>{
           data.name = 'newking';
        },1000)


     
    </script> 
  </body>
</html>